package org.ncibi.cytoscape.metscape.task;

import java.util.Arrays;

import javax.swing.JOptionPane;

import org.ncibi.cytoscape.metscape.data.Attributes;
import org.ncibi.cytoscape.metscape.network.MetScapeNetworks;
import org.ncibi.metab.network.MetabolicNetwork;
import org.ncibi.metab.network.NetworkType;
import org.ncibi.metab.ws.client.MetabolicNetworkService;
import org.ncibi.ws.HttpRequestType;
import org.ncibi.ws.Response;

import cytoscape.CyNetwork;
import cytoscape.Cytoscape;
import cytoscape.layout.CyLayoutAlgorithm;
import cytoscape.layout.CyLayouts;
import cytoscape.task.Task;
import cytoscape.task.TaskMonitor;
import cytoscape.task.ui.JTaskConfig;
import cytoscape.task.util.TaskManager;
import cytoscape.view.CyNetworkView;
import cytoscape.visual.VisualPropertyType;
import cytoscape.visual.VisualStyle;
import cytoscape.visual.calculators.Calculator;

public class ExpandInExistingNetworkTask implements Task {

	private String cid;
	private CyNetwork network;

	private TaskMonitor taskMonitor;
	private boolean interrupted = false;

	public static void expandUsing(String cid, CyNetwork network) {
		ExpandInExistingNetworkTask task = new ExpandInExistingNetworkTask(network,cid);
		configureAndRunTask(task);
	}
	
	public ExpandInExistingNetworkTask(CyNetwork network, String cid) {
		this.network = network;
		this.cid = cid;
	}
	
	private static void configureAndRunTask(ExpandInExistingNetworkTask task) {
		// Configure JTask Dialog Pop-Up Box
		JTaskConfig jTaskConfig = new JTaskConfig();
		jTaskConfig.setOwner(Cytoscape.getDesktop());
		jTaskConfig.displayCancelButton(true);
		jTaskConfig.displayStatus(true);

		// Execute Task in New Thread; pops open JTask Dialog Box.
		TaskManager.executeTask(task, jTaskConfig);
	}

	public void setTaskMonitor(TaskMonitor monitor)
			throws IllegalThreadStateException {
		taskMonitor = monitor;
	}

	public void halt() {
		interrupted = true;
	}

	public String getTitle() {
		return "Expand In Existing Network";
	}

	public void run() {
		try {
			taskMonitor.setPercentCompleted(-1);
			taskMonitor.setStatus("Querying database...");
			
			int taxid = Attributes.network.getIntegerAttribute(network.getIdentifier(), "Taxid");
			NetworkType networkType = NetworkType.toNetworkType(Attributes.network.getStringAttribute(network
					.getIdentifier(), "NetworkType"));
			
			Response<MetabolicNetwork> serverResponse;
			MetabolicNetworkService service = new MetabolicNetworkService(
					HttpRequestType.POST);
			serverResponse = service.retrieveNetworkOfTypeForCidsAndGeneids(
					networkType, Arrays.asList(cid), 
					null, taxid);
			
			if (serverResponse == null || !serverResponse.getResponseStatus().isSuccess() || interrupted)
				throw new Exception();

			
			MetabolicNetwork sourceNetwork = serverResponse.getResponseValue();
			if (sourceNetwork == null || interrupted)
				throw new Exception();
			
			network = MetScapeNetworks.expandInExistingNetwork(cid, sourceNetwork, network);
			
			
			if (network == null) {
				JOptionPane.showMessageDialog(Cytoscape.getDesktop(), 
						"No expansion relations were found for the selected node.", 
						"Relations Not Found", JOptionPane.INFORMATION_MESSAGE); 
			}
			
			else {
				CyNetworkView view = Cytoscape.getNetworkView(network.getIdentifier());
				
				//workaround for edge label redraw problem
				VisualStyle style = view.getVisualStyle();
				Calculator edgeLabelCalculator = style.getEdgeAppearanceCalculator().getCalculator(VisualPropertyType.EDGE_LABEL);
				style.getEdgeAppearanceCalculator().removeCalculator(VisualPropertyType.EDGE_LABEL);
				view.redrawGraph(true,true);
				style.getEdgeAppearanceCalculator().setCalculator(edgeLabelCalculator);
				view.redrawGraph(true,true);
				CyLayoutAlgorithm layout = CyLayouts.getLayout("force-directed");
				layout.doLayout(Cytoscape.getCurrentNetworkView(), taskMonitor);
			}
			taskMonitor.setStatus("Complete");
			taskMonitor.setPercentCompleted(100);

		} catch (Throwable t) {
			if (!interrupted)
				taskMonitor.setException(t, "Network expansion failed");
		}

	}
}
